
// Copyright (c) WanSheng Intelligent Corp. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.


#ifndef IDR_MGT_SHARED_LIBS_CLIENT_API_IAGENT_REDIS_API_H_
#define IDR_MGT_SHARED_LIBS_CLIENT_API_IAGENT_REDIS_API_H_


#include <hiredis.h>

#ifdef __cplusplus
extern "C" {
#endif


/******* Redis resource value format *************
type:   HSET
key:    v:p:[device id]:[resource ID]
value format: t={f|b|s|NA};v={value};tm={time}

127.0.0.1:6379> hgetall v:p:046e5f51b67c_ttt:/mmmm
1) "ba"
2) "t=f;v=104;tm=1683971303"
3) "fa"
4) "t=f;v=0;tm=1683971303"
***************************************************/

typedef enum {
    Redis_Value_NA = '\0',
    Redis_Value_Float = 'f',
    Redis_Value_Bool = 'b',
    Redis_Value_String = 's'
} Redis_Value_Type;

typedef struct
{
    Redis_Value_Type value_type;
    time_t time;
    union
    {
        bool bv;
        double fv;
        char* sv;
    };
} redis_value_t;

typedef struct
{
    char* property;
    redis_value_t value;
} redis_property_value_t;

/*
    @brief:    return the redis key used for the valeue of a resource of device
*/
char* wa_redis_value_key(const char* di,
    const char* res, char* buf, int buf_len);

/*
    @brief:    parse the value data
*/
bool wa_redis_parse_value(const char* value_str, redis_value_t* value);

void wa_redis_value_clean(redis_value_t* value);


void wa_redis_free_values(redis_property_value_t* values, int size);

/*
    @brief:    Establish a connection to the redis.
                Note: the caller is responsible for releasing it.
*/
redisContext* wa_redis_connect(int timeout_ms);


typedef enum
{
    Device_Status = 0,
    Data_Value,
    Agent_Info,
    DSS_Value,
    AMS_Config_Update,
    AMS_Software_Update,

    Other_Sub = 100,
    Quit_Monitor
} REDIS_EVENT_T;


/*
    @brief   Callback prototype for the redis event
    @param   subject:
             Data_Value - {di}:{res}:{property - optional}
             AMS_Config_Update - {software name}:{target type}:{target id}

*/
typedef void (*WA_REDIS_CALLBACK)(REDIS_EVENT_T event, char* subject, void* event_data, void* user_data);


/*
    @brief      decompose the subject of redis published event.
                It should in format of {part 1}:{part 2}:{part 3}.
                Note: the subject will splited by changing ':' to '\0'
    @return     the part 1    
*/
char* wa_redis_subject_decompose(char* subject, char** part2, char** part3);

/*
    @brief      decompose the title of AMS config event
    @return     the software name    
*/
char* wa_redis_subject_AMS_CFG(char* subject, char** target_type, char** target_id);


int wa_redis_start_monitor(WA_REDIS_CALLBACK callback, void* user_data);

int wa_redis_start_monitor_with_channel(WA_REDIS_CALLBACK callback, void* user_data, char* channels);


// if c is NULL, the funciton will try to setup a connection locally
char* wa_redis_read_dss(redisContext* c,
    const char* group,
    const char* dss,
    char* buffer,
    int size,
    time_t* tm);

redis_property_value_t* wa_redis_read_resource(redisContext* c,
    const char* di,
    const char* res,
    int* property_num);

bool wa_redis_read_property(redisContext* c,
    const char* di,
    const char* res,
    const char* pt,
    redis_value_t* value);

#ifdef __cplusplus
}
#endif

#endif /* IDR_MGT_SHARED_LIBS_CLIENT_API_IAGENT_REDIS_API_H_ */
